#include <android/log.h>
#include "MyManager.h"
#include "JsonAnalysis.h"
#include "FileClientSdk/FileClientSdk.h"

#define TAG		"ClientSdk"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

void OnFileServerStatusCallback(CallbackStatuTypes type, StatusInfo *pStatus, void* user)
{
	CMyManager *pMan = (CMyManager *)user;

	if (!pMan)
		return;

	switch (type)
	{
	case Status_online:
		pMan->m_pCallback(26, NULL, 0);
		LOGI("OnFileServerStatusCallback FileServer Connect Success!(%i)", __LINE__);
		pMan->m_bFileServerValid = true;
		break;
	case Status_offline:
		pMan->m_pCallback(27, NULL, 0);
		LOGI("OnFileServerStatusCallback FileServer Connect Faild!(%i)", __LINE__);
		pMan->m_bFileServerValid = false;
		break;
	case Status_uploadSuccess:
		pMan->UpdataFileInfo(pStatus->szFileName, pStatus->nWantFileSize);
		break;
	case Status_downloadSuccess:
		pMan->m_pCallback(29, pStatus->szFileName, strlen(pStatus->szFileName));
		LOGI("OnFileServerStatusCallback Download Success! %s(%i)", pStatus->szFileName, __LINE__);
		break;
	case Status_downloadFaild:
		pMan->m_pCallback(31, pStatus->szFileName, strlen(pStatus->szFileName));
		LOGI("OnFileServerStatusCallback Download Faild! %s(%i)", pStatus->szFileName, __LINE__);
		break;
	case Status_openfileFaild:
		pMan->m_pCallback(30, pStatus->szFileName, strlen(pStatus->szFileName));
		break;
	case Status_upload:
	{
		string strJson;

		CJsonAnalysis::FileStatus(strJson, pStatus->szFileName, pStatus->nWantFileSize, pStatus->nTotalSize);
		pMan->m_pCallback(32, strJson.c_str(), strJson.length());
		break;
	}
	case Status_download:
	{
		string strJson;

		CJsonAnalysis::FileStatus(strJson, pStatus->szFileName, pStatus->nWantFileSize, pStatus->nTotalSize);
		pMan->m_pCallback(33, strJson.c_str(), strJson.length());
		break;
	}
	default:
		break;
	}
}

CMyManager::CMyManager(OnMessageCallback callback)
	: m_bExit(false)
	, m_pMedia(NULL)
	, m_pCmd(NULL)
	, m_nTerminalId(0)
	, m_pCallback(callback)
	, m_bFileServerValid(false)
	, m_bFirstConnect(true)
{
	memset(m_szSvrIP, 0x00, 16);	
}

CMyManager::~CMyManager(void)
{
	Stop();
}

bool CMyManager::StartApp(int nTerminalId, const char *pSvrIp, unsigned short usPort)
{
	memcpy(m_szSvrIP, pSvrIp, 16);
	m_usPort = usPort;
	m_nTerminalId = nTerminalId;

	m_bExit = false;
	m_bFirstConnect = true;
	m_bFileServerValid = false;

	InitLib(OnFileServerStatusCallback, nTerminalId, this);

	m_pCmd = new CCmdChannel(this);
	m_pCmd->Start();

	return StartThread();
}

void CMyManager::Stop(void)
{
	m_bExit = true;

	WaitForStop();

	ReleaseLib(0);

	if (m_pCmd)
	{
		delete m_pCmd;
		m_pCmd = NULL;
	}

	if (m_pMedia)
	{
		delete m_pMedia;
		m_pMedia = NULL;
	}

	while (m_lstRecvData.size())
	{
		LPRecvDataInfo pRecvData = NULL;

		{
			CAutoLock autoLock(&m_lockRecvData);
			pRecvData = (LPRecvDataInfo)m_lstRecvData.front();
			m_lstRecvData.pop_front();
		}

		if (pRecvData)
		{
			if (pRecvData->pData)
			{
				delete[] pRecvData->pData;
				pRecvData->pData = NULL;
			}

			delete pRecvData;
			pRecvData = NULL;
		}
	}
}

char *CMyManager::GetSvrIp(void)
{
	return m_szSvrIP;
}

unsigned short CMyManager::GetSvrPort(void)
{
	return m_usPort;
}

int	CMyManager::GetTerminalId(void)
{
	return m_nTerminalId;
}

void CMyManager::PutRecvData(RecvDataInfo *pRecv)
{
	CAutoLock autoLock(&m_lockRecvData);
	m_lstRecvData.push_back(pRecv);
}

bool CMyManager::GetUserInfo(char *pOutBuf, int *len)
{
	return m_pCmd->GetUserInfo(pOutBuf, len);
}

bool CMyManager::GetUserList(char *pOutBuf, int *len)
{
	return m_pCmd->GetUserList(pOutBuf, len);
}

bool CMyManager::GetMeetingFileList(char *pOutBuf, int *len)
{
	return m_pCmd->GetMeetingFileList(pOutBuf, len);
}

bool CMyManager::GetMeetingIssueList(char *pOutBuf, int *len)
{
	return m_pCmd->GetMeetingIssueList(pOutBuf, len);
}

bool CMyManager::GetMeetingVoteList(char *pOutBuf, int *len)
{
	return m_pCmd->GetMeetingVoteList(pOutBuf, len);
}

int CMyManager::UserLogin(const char *pUserName, const char *pPassWord, char *outMsg, int *msgLen)
{
	return m_pCmd->SendUserVerify(pUserName, pPassWord, outMsg, msgLen);
}

bool CMyManager::UserSignControl(int nControlType)
{
	return m_pCmd->UserSignControl(nControlType);
}

bool CMyManager::AllUserSign(const char *pJson)
{
	return m_pCmd->AllUserSign(pJson);
}

bool CMyManager::TerminalUserSign(int nUserId, const char *pUserName, const char *pFilePath, const char *pFileName)
{
	if (m_bFileServerValid)
	{
		char szRemoteFilePath[512] = { 0 };

		if (SendFileToServer(0, pFilePath, pFileName, szRemoteFilePath) == 0)
		{
			UploadFileInfo *uploadFileInfo = new UploadFileInfo;

			uploadFileInfo->nFileType = 6;
			uploadFileInfo->strRemoteFilePath = szRemoteFilePath;
			uploadFileInfo->strFileName = pFileName;

			uploadFileInfo->nIsSign = 1;
			uploadFileInfo->nUserId = nUserId;
			uploadFileInfo->strUserName = pUserName;

			m_lstSendFile[pFilePath] = uploadFileInfo;

			return true;
		}
	}

	return false;
}

int CMyManager::IssueControl(int nIssueId, int nControlType)
{
	return m_pCmd->IssueControl(nIssueId, nControlType);
}

int CMyManager::VoteControl(int nVoteId, int nControlType)
{
	return m_pCmd->VoteControl(nVoteId, nControlType);
}

int CMyManager::VoteMsg(const char *pMsg, int nLen)
{
	return m_pCmd->VoteMsg(pMsg, nLen);
}

int CMyManager::CenterControl(int nControlType)
{
	return m_pCmd->CenterControl(nControlType);
}

bool CMyManager::SendChatMessage(const char *pMessage)
{
	return m_pCmd->SendChatMessage(pMessage);
}

bool CMyManager::SendMeetingService(const char *pMessage)
{
	return m_pCmd->SendMeetingService(pMessage);
}

int CMyManager::DownLoadFile(const char *pSvrFilePath, const char *pSaveFilePath)
{
	if (m_bFileServerValid)
		return GetFileFromServer(0, pSaveFilePath, "", pSvrFilePath);

	return -2;
}

int CMyManager::UpLoadFile(const char *pFilePath, const char *pFileName, int nFileType)
{
	if (m_bFileServerValid)
	{
		char szRemoteFilePath[512] = { 0 };

		if (SendFileToServer(0, pFilePath, pFileName, szRemoteFilePath) == 0)
		{
			UploadFileInfo *uploadFileInfo = new UploadFileInfo;

			uploadFileInfo->nFileType = nFileType;
			uploadFileInfo->strRemoteFilePath = szRemoteFilePath;
			uploadFileInfo->strFileName = pFileName;
			uploadFileInfo->nIsSign = 0;

			m_lstSendFile[pFilePath] = uploadFileInfo;

			return 0;
		}
	}	

	return -1;
}

int CMyManager::SendWbData(const char *pWbData, int nDataLen)
{
	return m_pMedia->SendDataToServer(ANDROID_WB_DATA, pWbData, nDataLen);
}

int CMyManager::SendCommentData(const char *pWbData, int nDataLen)
{
	return m_pMedia->SendDataToServer(ANDROID_COMMENT_DATA, pWbData, nDataLen);
}

void CMyManager::HandleRecvWbData(const char *pWbData, int nDataLen)
{
	m_pCallback(34, pWbData, nDataLen);
}

void CMyManager::HandleRecvCommentData(const char *pWbData, int nDataLen)
{
	m_pCallback(39, pWbData, nDataLen);
}

int CMyManager::UpdataFileInfo(const char *pFilePath, int nFileLen)
{
	int nRet = -1;

	map<string, UploadFileInfo *>::iterator iter = m_lstSendFile.find(pFilePath);
	if (iter != m_lstSendFile.end())
	{
		UploadFileInfo *pFileInfo = iter->second;
		if (pFileInfo)
		{
			if (pFileInfo->nIsSign == 0)
			{
				TerminalFileInfo terminalFile;

				terminalFile.nFileType = pFileInfo->nFileType;
				terminalFile.nTerminalId = m_nTerminalId;
				terminalFile.strFileName = pFileInfo->strFileName;

				terminalFile.nFileSize = nFileLen;
				terminalFile.strFilePath = pFileInfo->strRemoteFilePath;

				nRet = m_pCmd->UploadFileInfo(&terminalFile);
			}
			else if (pFileInfo->nIsSign == 1)
			{
				if (m_pCmd->TerminalUserSign(pFileInfo->nUserId, pFileInfo->strUserName.c_str(), pFileInfo->strRemoteFilePath.c_str()))
				{
					nRet = 0;
				}					
			}			

			m_pCallback(28, pFilePath, strlen(pFilePath));

			delete pFileInfo;
			pFileInfo = NULL;
		}

		m_lstSendFile.erase(iter);
	}

	return nRet;
}

void CMyManager::SetCmdChannelIsOk(void)
{
	if (m_bFirstConnect)
	{
		m_pMedia = new CMediaChannel(this);
		m_pMedia->Start();

		m_bFirstConnect = false;
	}	
}

bool CMyManager::SendExtendData(const char *pMessage)
{
	return m_pCmd->SendExtendData(pMessage);
}

void CMyManager::ThreadProcMain(void)
{
	while (!m_bExit)
	{
		while (m_lstRecvData.size())
		{
			LPRecvDataInfo pRecvData = NULL;

			{
				CAutoLock autoLock(&m_lockRecvData);
				pRecvData = (LPRecvDataInfo)m_lstRecvData.front();
				m_lstRecvData.pop_front();
			}

			if (pRecvData)
			{
				HandleRecvData(pRecvData);

				if (pRecvData->pData)
				{
					delete[] pRecvData->pData;
					pRecvData->pData = NULL;
				}

				delete pRecvData;
				pRecvData = NULL;
			}
		}

		my_sleep(2);
	}
}

void CMyManager::HandleRecvData(RecvDataInfo *pRecv)
{
	switch (pRecv->nCmd)
	{
	case CMDCHANNEL_BREAK:
		m_pCallback(3, NULL, 0);
		break;
	case CMDCHANNEL_CONNECT:
		m_pCallback(1, NULL, 0);
		break;
	case MEDIACHANNEL_BREAK:
		m_pCallback(4, NULL, 0);
		break;
	case MEDIACHANNEL_CONNECT:
		m_pCallback(2, NULL, 0);
		break;
	case CMDCHANNEL_CONNECT_FAIL:
		m_pCallback(5, NULL, 0);
		break;
	case MEDIACHANNEL_CONNECT_FAIL:
		m_pCallback(6, NULL, 0);
		break;
	case CMD_S2T_MEETINGINFO:
		HandleMeetingIssued(pRecv);
		break;
	case CMD_S2T_USERSTATUS:
		m_pCallback(13, pRecv->pData, pRecv->nMsgLen);
		break;	
	case CMD_T2S_SIGNCONTROL:
		m_pCallback(14, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_SIGNSTATUS:
		m_pCallback(15, pRecv->pData, pRecv->nMsgLen);
		break;		
	case CMD_S2T_ISSUEUPDATE:
		m_pCallback(16, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_ISSUENOTICE:
		m_pCallback(17, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_VOTEUPDATE:
		m_pCallback(18, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_STARTVOTE:
		m_pCallback(20, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_STOPVOTE:
		m_pCallback(21, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_VOTESTATUS:
		m_pCallback(19, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_VOTERESULT_NOTICE:
		m_pCallback(22, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_T2S_CENTERCONTROL:
		m_pCallback(23, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_MESSAGE:
		m_pCallback(24, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_T2S_VOTECONTROL:
		m_pCallback(35, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_T2S_VOTE:
		m_pCallback(36, pRecv->pData, pRecv->nMsgLen);
		break;
	case HAVE_SAMETERMINALID:
		m_pCallback(37, NULL, 0);
		break;
	case CMD_S2T_FILEUPDATENOTICE:
		m_pCallback(38, pRecv->pData, pRecv->nMsgLen);
		break;
	case ANDROID_EXTEND_COMMOND:
		m_pCallback(40, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_S2T_QUIT_MEETING:
		m_pCallback(41, pRecv->pData, pRecv->nMsgLen);
		break;
	case CMD_T2S_STREAM_STATUS:
		m_pCallback(42, pRecv->pData, pRecv->nMsgLen);
		break;
	default:
		break;
	}
}

void CMyManager::HandleMeetingIssued(RecvDataInfo *pRecv)
{
	if (CJsonAnalysis::AnalysIssuedMeeting(pRecv->pData, &m_stMeetingInfo))
	{
		LOGI("CMyManager::HandleMeetingIssued  FileServerIp:%s:%d (%i)", m_stMeetingInfo.strFileServerIP.c_str(), m_stMeetingInfo.nFileServerPort, __LINE__);

		ConnectFileServer(0, m_stMeetingInfo.strFileServerIP.c_str(), m_stMeetingInfo.nFileServerPort);
	}

	m_pCallback(7, pRecv->pData, pRecv->nMsgLen);
}
